﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Cache;
using System.Security.Cryptography;
using System.Text;
using System.Web;

namespace YunShop_WebAPI.BLL.SxfPay
{
    public class LFTPayDoing
    {
        public static string url = "http://newfront.liantuobank.com/NewFront/base/gateway.in";
        public static string input_charset = "UTF-8";
        public static string version = "1.0";
        public static string sign_type = "MD5";


        /*测试账号
         * partner_id：18060410173207886（通过代理商后台获取pid）
         * core_merchant_no：EW_N5772984681（代理商后台获取的商户ID core_merchant_no=商户ID）
         * key：78bc1ac50be17004b58edea930c70c78（代理商后台获取key）
         * merchant_no：EW_N8366110628（代理商后台获取的商户ID对应的门店ID merchant_no=门店ID）
         */
        //public static string partner_id = "18080616062178511";
        //public static string core_merchant_no = "EW_N5946005323";
        //public static string key = "f0329e22fb506a4e26ccb29b0a6c5af3";
        //public static string merchant_no = "EW_N4130797151";



        /// <summary>
        /// 
        /// </summary>
        /// <param name="url">接口地址url</param>
        /// <param name="pms">请求参数键值对</param>
        /// <param name="state">结果</param>
        /// <param name="result">响应信息</param>
        /// <param name="message">结果信息</param>
        /// <param name="origin">打印显示</param>
        /// <param name="timeout">过期时间</param>
        /// <returns></returns>
        public static bool Doing(String url, string key, Dictionary<String, String> pms, ref String state, ref Dictionary<String, Object> result, ref String message, ref String origin, int timeout)
        {
            String sign;
            sign = CreateSign(pms, key, "utf-8");

            pms["sign"] = sign; //根据附录签名规则签名

            string strData;

            string postData = "";
            foreach (KeyValuePair<String, String> dic in pms)
            {
                if (String.IsNullOrEmpty(dic.Value)) continue;

                if (postData.Length > 0) postData += "&";
                postData += dic.Key + "=" + dic.Value;
            }

            //CLog.Write("Pay:DoingData:" + postData);
            byte[] byteData = Encoding.UTF8.GetBytes(postData);

            result = new Dictionary<String, Object>();

            state = "0";

            try
            {
                strData = HttpPost(url, null, byteData, timeout, null, null);

                origin = strData;

                result = (Dictionary<String, Object>)Json2Dictionary(strData);

                if (ContainInStringDictionary(result, "state"))
                {
                    state = GetStringDictionary(result, "state");
                    message = GetStringDictionary(result, "obj");
                }
                else if (ContainInStringDictionary(result, "isSuccess"))
                {
                    state = GetStringDictionary(result, "isSuccess");
                    message = GetStringDictionary(result, "message");
                }
                else if (ContainInStringDictionary(result, "code"))
                {
                    state = GetStringDictionary(result, "code");
                    message = GetStringDictionary(result, "message");

                    return ("SUCCESS".Equals(state) || "S".Equals(state));
                }
                else
                {
                    throw new Exception("接口不规范");
                }
            }
            catch (WebException w)
            {
                message = "请求接口失败";
                if (w.Status == WebExceptionStatus.Timeout)
                {
                    message = "访问超时";
                }
            }
            catch (Exception)
            {
                message = "系统异常";
            }


            return ("1".Equals(state) || "S".Equals(state));
        }



        /// <summary>
        /// 获取签名   验签的加密方式，默认只支持MD5
        /// </summary>
        /// <param name="paras"></param>
        /// <param name="key">验签参数key</param>
        /// <param name="enc">编码格式utf-8</param>
        /// <returns>返回验签字符串</returns>
        public static String CreateSign(Dictionary<String, String> paras, String key, String enc)
        {
            List<String> lst = new List<String>();
            lst.AddRange(paras.Keys);
            lst.Sort();//元素按照字典序排序

            String data = "";
            //字典序拼接键值对，例如：key1=value1&key2=value2&key3=value3
            foreach (String k in lst)
            {
                String v = paras[k];
                if (!String.IsNullOrEmpty(v) && !"sign".Equals(k) && !"key".Equals(k))
                {
                    if (data.Length > 0) data += "&";
                    data += k + "=" + v;
                }
            }
            //在data最后拼接key
            if (!"".Equals(key))
            {
                data += "&key=" + key;
            }

            String sign;
            try
            {
                sign = GetMD5(data, enc);//加密MD5
            }
            catch (Exception)
            {
                sign = "";
            }

            if (sign == null) sign = "";

            char[] a = sign.ToCharArray();

            for (int i = 0; i < a.Length; i++)
            {
                a[i] = (char)(a[i] ^ 't');
            }

            //sign = new String(a);

            return sign;//返回签名
        }


        //MD5加密方法
        private static string GetMD5(string s, string _input_charset)
        {
            byte[] data = Encoding.GetEncoding(_input_charset).GetBytes(s);

            using (var md5 = new MD5CryptoServiceProvider())
            {
                byte[] buffer = md5.ComputeHash(data);
                StringBuilder builder = new StringBuilder(0x20);
                for (int i = 0; i < buffer.Length; i++)
                {
                    builder.Append(buffer[i].ToString("x").PadLeft(2, '0'));
                }
                return builder.ToString();
            }

        }


        /// <summary>
        /// 把对象转成json字符串
        /// </summary>
        /// <param name="o">对象</param>
        /// <returns>json字符串</returns>
        /// <summary>
        /// 将字典类型序列化为json字符串
        /// </summary>
        /// <typeparam name="TKey">字典key</typeparam>
        /// <typeparam name="TValue">字典value</typeparam>
        /// <param name="dict">要序列化的字典数据</param>
        /// <returns>json字符串</returns>
        public static string SerializeDictionaryToJsonString<TKey, TValue>(Dictionary<TKey, TValue> dict)
        {
            if (dict.Count == 0)
                return "";

            //string jsonStr = (new JavaScriptSerializer()).Serialize(dict);
            string jsonStr = SerializerHelper.SerializeToString(dict);
            return jsonStr;
        }


        /// <summary>
        /// 接收请求
        /// </summary>
        private static string HttpPost(string targetURL, string strContentType, byte[] data, int timeOut, string htmlencoding, WebProxy proxy)
        {

            HttpWebResponse response = HttpPost(targetURL, strContentType, data, timeOut, proxy);



            if (String.IsNullOrEmpty(htmlencoding))
                htmlencoding = "UTF-8"; //默认编码;
            string htmlencodingOfResult = response.ContentEncoding;
            if (htmlencodingOfResult == null || htmlencodingOfResult.Length < 1)
            {
                htmlencodingOfResult = htmlencoding;
            }
            StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding(htmlencodingOfResult));
            string html = reader.ReadToEnd();
            reader.Close();
            response.Close();

            return html;
        }

        /// <summary>
        /// 发送post请求
        /// </summary>
        internal static HttpWebResponse HttpPost(string targetURL, string strContentType, byte[] data, int timeOut, WebProxy proxy)
        {

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(targetURL);

            HttpRequestCachePolicy policy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore);
            request.CachePolicy = policy;
            request.Timeout = timeOut;
            request.KeepAlive = true;
            request.Method = "POST";
            if (String.IsNullOrEmpty(strContentType))
                strContentType = "application/x-www-form-urlencoded"; //application/x-www-form-urlencoded
            request.ContentType = strContentType;
            request.UserAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C; .NET4.0E)";

            request.ContentLength = data.Length;
            Stream writer = request.GetRequestStream();
            writer.Write(data, 0, data.Length);
            writer.Flush();
            writer.Close();


            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            if (response.StatusCode != HttpStatusCode.OK)
            {

            }

            return response;
        }


        private static void Json2DictionaryArrayHelper(ref String json, List<Object> lst)
        {
            if (json == null) return;

            if (!json.StartsWith("[")) return;

            json = json.Substring(1);

            while (!String.IsNullOrEmpty(json))
            {
                json = json.Trim();

                if (json.StartsWith("]"))
                {
                    json = json.Substring(1).Trim();
                    return;
                }


                if (json.StartsWith(","))
                {
                    json = json.Substring(1).Trim();
                    continue;
                }

                if (json.StartsWith("{"))
                {
                    Dictionary<String, Object> subresult = new Dictionary<String, Object>();
                    Json2DictionaryHelper(ref json, subresult);
                    lst.Add(subresult);
                }
                else if (json.StartsWith("["))
                {
                    List<Object> sublst = new List<Object>();
                    Json2DictionaryArrayHelper(ref json, sublst);
                    lst.Add(sublst);
                }
                else
                {
                    json = json.Substring(1).Trim();
                    continue;
                }
            }
        }

        private static void Json2DictionaryHelper(ref String json, Dictionary<String, Object> result)
        {
            if (json == null) return;

            if (!json.StartsWith("{")) return;

            json = json.Substring(1);

            while (!String.IsNullOrEmpty(json))
            {
                json = json.Trim();

                if (json.StartsWith("}"))
                {
                    json = json.Substring(1).Trim();
                    return;
                }

                if (json.StartsWith(","))
                {
                    json = json.Substring(1).Trim();
                    continue;
                }

                int pos;
                String key;
                if (json.StartsWith("\""))
                {
                    json = json.Substring(1);
                    pos = json.IndexOf("\"");
                    if (pos <= 0) break;
                    key = json.Substring(0, pos);
                    json = json.Substring(pos + 1);
                    json = json.Trim();
                }
                else
                {
                    pos = json.IndexOf(":");
                    if (pos <= 0) break;
                    key = json.Substring(0, pos);
                    json = json.Substring(pos);
                    json = json.Trim();
                }
                if (!json.StartsWith(":")) break;

                json = json.Substring(1);
                json = json.Trim();


                key = key.Trim();
                if (String.IsNullOrEmpty(key)) break;

                json = json.Trim();

                if (json.StartsWith("{"))
                {
                    Dictionary<String, Object> subresult = new Dictionary<String, Object>();
                    Json2DictionaryHelper(ref json, subresult);
                    result[key] = subresult;
                }
                else if (json.StartsWith("["))
                {
                    List<Object> lst = new List<Object>();
                    Json2DictionaryArrayHelper(ref json, lst);
                    result[key] = lst;
                }
                else
                {
                    String value;
                    if (json.StartsWith("\""))
                    {
                        json = json.Substring(1);
                        pos = json.IndexOf("\"");
                        if (pos < 0) break;
                        value = json.Substring(0, pos);
                        json = json.Substring(pos + 1);
                        json = json.Trim();
                    }
                    else
                    {
                        pos = json.IndexOf(",");
                        if (pos < 0)
                        {
                            pos = json.IndexOf("}");
                        }
                        else
                        {
                            int pos1 = json.IndexOf("}");
                            if (pos1 >= 0 && pos1 < pos) pos = pos1;
                        }
                        if (pos >= 0)
                        {
                            value = json.Substring(0, pos);
                            json = json.Substring(pos);
                            json = json.Trim();
                        }
                        else
                        {
                            value = json;
                            json = "";
                        }
                    }
                    if (json.StartsWith(","))
                    {
                        json = json.Substring(1);
                        json = json.Trim();
                    }

                    value = value.Replace("\x01", "\\\"");
                    value = value.Replace("\x02", "\\{");
                    value = value.Replace("\x03", "\\}");

                    result[key] = value;
                }
            }
        }


        internal static Object Json2Dictionary(String json)
        {
            if (json == null) return null;

            json = json.Trim();

            json = json.Replace("\\\\", "\\");

            json = json.Replace("\\\"", "\x01");
            json = json.Replace("\\{", "\x02");
            json = json.Replace("\\}", "\x03");

            if (json.StartsWith("["))
            {
                List<Object> result = new List<Object>();
                Json2DictionaryArrayHelper(ref json, result);
                return result;
            }
            else
            {
                Dictionary<String, Object> result = new Dictionary<String, Object>();
                Json2DictionaryHelper(ref json, result);
                return result;
            }
        }
        public static bool ContainInStringDictionary(Dictionary<String, Object> dic, String key)
        {
            if (dic == null) return false;
            lock (dic)
            {
                return dic.ContainsKey(key);
            }
        }

        public static String GetStringDictionary(Dictionary<String, Object> dic, String key)
        {
            if (dic == null) return "";
            lock (dic)
            {
                if (!dic.ContainsKey(key)) return "";

                String value = (String)dic[key];
                if (!String.IsNullOrEmpty(value) && "null".Equals(value, StringComparison.CurrentCultureIgnoreCase))
                {
                    value = "";
                }

                return value;
            }
        }

    }
}
